Skip to content

feat(highcharts): implement waterfall-basic#5746

Merged
MarkusNeusinger merged 5 commits intomainfrom
implementation/waterfall-basic/highcharts
May 6, 2026
Merged

feat(highcharts): implement waterfall-basic#5746
MarkusNeusinger merged 5 commits intomainfrom
implementation/waterfall-basic/highcharts

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented May 6, 2026

Implementation: waterfall-basic - python/highcharts

Implements the python/highcharts version of waterfall-basic.

File: plots/waterfall-basic/implementations/python/highcharts.py

Parent Issue: #777


🤖 impl-generate workflow

github-actions Bot added 2 commits May 6, 2026 01:09
Regen from quality 91. Addressed:
- theme-adaptive colors (light/dark background support)
- Okabe-Ito palette (green for positive, orange for negative, blue for totals)
- theme-suffixed output files (plot-light.png/html, plot-dark.html)
- proper title format and styling
- network resilience with CDN fallback
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 6, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot renders as a blank canvas with only the warm off-white background (#FAF8F1) visible. No waterfall chart, bars, axes, labels, title, or any data visualization elements are present. The container exists but is completely empty.

Dark render (plot-dark.png): Similarly blank with the warm near-black background (#1A1A17) visible. No chart content, data visualization, axes, labels, title, or any elements are rendered. Both renders are identically empty.

Legibility verdict: FAIL — No content is visible to evaluate. The charts completely failed to render.

Score: 0/100

Category Score Max
Visual Quality 0 30
Design Excellence 0 20
Spec Compliance 0 15
Data Quality 0 15
Code Quality 0 10
Library Mastery 0 10
Total 0 100

Critical Failure: AR-04 (EMPTY_PLOT)

The implementation produces blank/empty PNG images with no visible content.

Root Cause Analysis

The code implements a fallback mechanism (lines 147-185) that:

  1. Attempts to download Highcharts JS from CDN
  2. If download fails/times out → falls back to <script src="..."> tags pointing to external CDN

Problem: Headless Chrome with file:// URLs cannot load external CDN scripts due to CORS/security restrictions. The library documentation at prompts/library/highcharts.md explicitly warns:

"IMPORTANT: Headless Chrome cannot load external CDN scripts from file:// URLs. You MUST download Highcharts JS and embed it inline."

When the fallback occurs, the CDN scripts fail to load silently, Highcharts is never defined in the browser, and the chart initialization is skipped, leaving a blank plot.

Specific Issues Found

  1. AR-04 (EMPTY_PLOT): Both light and dark renders are completely blank — no waterfall chart, no bars, no axes, no labels, no title
  2. Library Loading Failure: Highcharts JavaScript fails to load due to fallback mechanism using CDN links with file:// protocol
  3. Incomplete Error Handling: The WebDriverWait (lines 207-211) only waits 15 seconds then sleeps 3 seconds, but if the script never loads, the timeout is inadequate
  4. Missing Inline Script Guarantee: The code should always download Highcharts JS inline; the fallback should only be a last resort with logging, not silently try CDN

What Needs to be Fixed

High Priority:

  1. Remove the fallback to CDN links entirely
  2. Ensure Highcharts JS (and highcharts-more.js for waterfall) are always downloaded and embedded inline
  3. Add explicit error handling: if download fails, raise an exception rather than silently creating a blank plot
  4. Increase wait time for chart rendering (currently 3 seconds is insufficient)

Code improvements:

  • Line 148: The condition if highcharts_js and highcharts_more_js: should enforce this is mandatory, not optional
  • Lines 167-185: Remove the fallback CDN HTML template — it will never work with file://
  • Add logging/assertions to verify downloads succeeded before proceeding

Weaknesses

  • Highcharts JavaScript fails to load in headless Chrome environment
  • Fallback mechanism silently fails instead of raising an error
  • No validation that required scripts downloaded successfully
  • Insufficient wait time for chart rendering

Verdict: REJECTED

Score: 0/100 — Implementation produces completely blank plots. The chart fails to render due to Highcharts library not loading. This is a critical runtime failure that must be fixed before the implementation can be evaluated for quality.

Next steps: Fix the Highcharts loading mechanism to ensure scripts are always downloaded inline and properly validated before chart initialization.

@github-actions
Copy link
Copy Markdown
Contributor Author

github-actions Bot commented May 6, 2026

🔧 AI Review Produced No Score — Auto-Retrying

The Claude Code Action ran but didn't write quality_score.txt. Auto-retrying review once...


🤖 impl-review

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 6, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): Background color is correct (#FAF8F1 warm off-white), but the plot area is completely blank. No title, axis labels, tick labels, or waterfall chart bars are visible. The page renders but no Highcharts content appears.

Dark render (plot-dark.png): Background color is correct (#1A1A17 warm near-black), but the plot area is completely blank. No title, axis labels, tick labels, or waterfall chart bars are visible. The page renders but no Highcharts content appears.

CRITICAL FAILURE: Both renders show completely empty canvases. The HTML configuration is valid, but the JavaScript does not execute, preventing any chart rendering.

Score: 0/100

Category Score Max
Visual Quality 0 30
Design Excellence 0 20
Spec Compliance 0 15
Data Quality 0 15
Code Quality 0 10
Library Mastery 0 10
Total 0 100

Auto-Reject Triggered

AR-04: EMPTY_PLOT — Both plot-light.png and plot-dark.png show completely blank images with no chart content.

Root Cause Analysis

The implementation attempts to download Highcharts JS from the CDN (lines 131-145). When the download fails or times out, it falls back to CDN <script src="..."> tags (lines 168-172). However, this fallback does not work with the file:// protocol used by Selenium in headless Chrome. CDN links cannot load external resources from local file:// URLs due to CORS restrictions.

Key issue: The code structure at lines 148-185 creates two different HTML templates based on whether the download succeeded. The fallback assumes CDN links will work, but they won't in headless Chrome.

Strengths

  • Chart options JSON is well-formed with correct theme tokens
  • Background colors are correctly set to #FAF8F1 (light) and #1A1A17 (dark)
  • Title, axis labels, and data label formatters are properly configured

Weaknesses

  • AR-04: Chart fails to render entirely — no waterfall bars, no axis labels, no title visible in either theme
  • Fallback mechanism broken: CDN script tags do not work with file:// protocol in headless Chrome
  • Missing guarantee of inline scripts: If download fails, script should still be embedded inline (with a stub or placeholder) rather than relying on broken CDN fallback
  • Implementation does not follow highcharts.md critical requirement: "You MUST download Highcharts JS and embed it inline"

Issues Found

  1. CRITICAL - AR-04: Empty Plot

    • Fix: Remove CDN fallback. If JS download fails, raise an exception to alert the developer. Do not attempt to load external scripts via file:// protocol.
    • Alternative: Provide a local copy of Highcharts JS in the repository or use --disable-web-resources more carefully to still allow protocol handlers to work.
  2. Script Loading Strategy

    • Current: Try download → fallback to CDN (broken)
    • Fix: Try download → raise error if it fails (fail-fast approach)
    • Reason: Highcharts.js is ~500KB; headless screenshot generation requires the script to be available inline

AI Feedback for Next Attempt

The chart must render before it can be scored. The primary issue is the fallback to CDN links which cannot load in headless Chrome. Restructure the script acquisition:

  1. Attempt to download Highcharts JS with error handling that explicitly catches timeouts/failures
  2. Do NOT fall back to CDN links — they will not work with file:// protocol
  3. If download fails after retries, raise an exception and let the pipeline know the implementation cannot run
  4. Ensure both highcharts.js and highcharts-more.js are downloaded and embedded inline before passing to Selenium

Verify the fix works by running the implementation locally and confirming both plot-light.png and plot-dark.png contain visible waterfall charts with title, axis labels, and data labels.

Verdict: REJECTED

Status: Auto-reject (AR-04). Chart fails to render.
Next step: Fix the JS loading mechanism to guarantee inline script embedding and retry generation.

@github-actions github-actions Bot added the ai-review-failed AI review action failed or timed out label May 6, 2026
@github-actions
Copy link
Copy Markdown
Contributor Author

github-actions Bot commented May 6, 2026

❌ AI Review Failed (auto-retry exhausted)

The AI review action completed but did not produce valid output files. Auto-retry already tried once.

What happened:

  • The Claude Code Action ran
  • No quality_score.txt file was created

Manual rerun:

gh workflow run impl-review.yml -f pr_number=5746

🤖 impl-review

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 6, 2026

AI Review - Attempt 1/3

Image Description

Light render (`plot-light.png`): The image shows only the warm off-white background (#FAF8F1) — correct for the light theme. There is no chart content whatsoever: no title, no axes, no bars, no labels, no legend. A faint hairline appears at the very bottom edge, likely the browser viewport boundary. The Highcharts waterfall chart failed to render entirely. Legibility verdict: FAIL — no text exists to evaluate, because the chart never drew.

Dark render (`plot-dark.png`): The image shows only the warm near-black background (#1A1A17) — correct for the dark theme. Identical situation: no chart content, no title, no axes, no data bars. The chart failed to render in dark mode as well. Dark-on-dark failure does not apply because there is nothing rendered at all. Legibility verdict: FAIL — rendering failure, no content to assess.

Both renders confirm a complete chart rendering failure. The background colors are theme-correct (inline body style in the HTML is set before Highcharts initialises), but the Highcharts library itself never loaded or executed, so the chart container remains empty.

Score: 26/100

Category Score Max
Visual Quality 1 30
Design Excellence 0 20
Spec Compliance 0 15
Data Quality 14 15
Code Quality 7 10
Library Mastery 4 10
Total 26 100

Visual Quality (1/30)

  • VQ-01: Text Legibility (0/8) — No text rendered in either image
  • VQ-02: No Overlap (0/6) — No elements rendered
  • VQ-03: Element Visibility (0/6) — No chart elements visible; rendering failed completely
  • VQ-04: Color Accessibility (0/2) — Cannot evaluate; nothing rendered
  • VQ-05: Layout & Canvas (0/4) — Canvas shows only background; chart area empty
  • VQ-06: Axis Labels & Title (0/2) — None visible
  • VQ-07: Palette Compliance (1/2) — Background colors are correct (#FAF8F1 light / #1A1A17 dark); data colors cannot be verified since nothing rendered

Design Excellence (0/20)

  • DE-01: Aesthetic Sophistication (0/8) — Nothing rendered
  • DE-02: Visual Refinement (0/6) — Nothing rendered
  • DE-03: Data Storytelling (0/6) — Nothing rendered

Spec Compliance (0/15)

  • SC-01: Plot Type (0/5) — Waterfall type specified in code but never displayed
  • SC-02: Required Features (0/4) — Nothing rendered
  • SC-03: Data Mapping (0/3) — Nothing rendered
  • SC-04: Title & Legend (0/3) — Nothing rendered

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) — Code defines positive bars (Other Income), multiple negative bars (Product Costs, Operating Expenses, Marketing, R&D, Taxes), a starting total (Revenue) and an ending computed total (isSum: True for Net Income) — good waterfall feature coverage
  • DQ-02: Realistic Context (5/5) — Quarterly financial breakdown from revenue to net income is a classic, neutral, real-world waterfall use case
  • DQ-03: Appropriate Scale (4/4) — Revenue $500k, total deductions ~$362k, implied net income ~$158k (~68% cost ratio) — financially plausible proportions

Code Quality (7/10)

  • CQ-01: KISS Structure (3/3) — Clean linear structure: imports → theme tokens → data → chart options → HTML → screenshot
  • CQ-02: Reproducibility (2/2) — All data is hardcoded/deterministic; no random seed needed
  • CQ-03: Clean Imports (2/2) — All imports are used (json, os, tempfile, time, urllib.request, pathlib, selenium)
  • CQ-04: Code Elegance (0/2) — Critical rendering bug: makes the inline script path conditional on BOTH highcharts.js AND highcharts-more.js succeeding; if either returns None, falls back to CDN <script src> tags that headless Chrome cannot load on file:// URLs. Also uses hacky JSON-string placeholder injection (__FORMATTER_PLACEHOLDER__) to embed JS functions.
  • CQ-05: Output & API (0/1) — Generates plot-{THEME}.png and plot-{THEME}.html, but both PNG files are blank; output is not a valid plot

Library Mastery (4/10)

  • LM-01: Idiomatic Usage (2/5) — Correctly identifies waterfall as a native Highcharts series type and structures options correctly; but the critical CDN fallback bug (caused by misunderstanding of which modules waterfall needs) reveals incomplete library mastery
  • LM-02: Distinctive Features (2/5) — Attempts to leverage native Highcharts waterfall series with isSum property, inline JS formatter functions for y-axis labels and data labels — all Highcharts-distinctive; would score higher if it had rendered

Score Caps Applied

  • VQ-03 = 0 → cap at 49; raw score 26 is already below cap — no change

Strengths

  • Excellent data design: well-chosen financial categories with positive, negative, and total bars covering all waterfall chart features
  • Correct Highcharts API approach: native "type": "waterfall" series, isSum property, inline JS formatters for labels
  • Complete theme-adaptive chrome: all INK, INK_SOFT, GRID tokens correctly wired; backgrounds match #FAF8F1 / #1A1A17
  • Clean KISS code structure with no unnecessary functions or classes

Weaknesses

  • CRITICAL — Rendering failure (pipeline failure): The code makes inline JS rendering conditional on if highcharts_js and highcharts_more_js:; if highcharts_more_js download fails (returns None), it falls back to CDN <script src> tags which headless Chrome cannot load on file:// URLs. Both rendered PNGs are completely blank.
  • Unnecessary dependency on highcharts-more.js: The waterfall series type is built into the main highcharts.jshighcharts-more.js is only needed for boxplot, bubble, gauge, etc. Downloading it unnecessarily made the render conditional on an unneeded resource.
  • Hacky JS injection: Using "__FORMATTER_PLACEHOLDER__" strings in the JSON dict and then doing string-replace to inject raw JS is fragile; prefer constructing the full HTML template string with the JS functions embedded directly.

Issues Found

  1. CRITICAL — Blank render: highcharts-more.js is not needed for waterfall charts. Remove that download entirely. Make the render depend only on highcharts_js, and raise an error if that download fails rather than falling back to a CDN path that is guaranteed to fail in headless Chrome.
    • Fix: Remove the highcharts_more_js download block; change if highcharts_js and highcharts_more_js: to just if highcharts_js: (or make it unconditional with a mandatory download); delete the CDN fallback branch.
  2. Placeholder injection pattern: Replace the __FORMATTER_PLACEHOLDER__ approach by embedding the JS formatter functions directly in the HTML template string, avoiding JSON serialisation round-trips for JS code.

AI Feedback for Next Attempt

The rendering failure is the only blocker. Fix: (1) Remove highcharts-more.js download — waterfall is in highcharts.js alone. (2) Remove the CDN fallback entirely — it cannot work in headless Chrome. (3) Make the download unconditional: if it fails, let the exception propagate rather than silently producing a blank image. Once rendering works, the design bones are solid: theme tokens are correct, data is well-chosen, and the Highcharts waterfall API is used correctly.

Verdict: REJECTED

@github-actions github-actions Bot added quality:26 Quality score 26/100 ai-rejected Quality not OK, triggers update quality-poor Score < 50, needs fundamental fixes labels May 6, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels May 6, 2026
@github-actions
Copy link
Copy Markdown
Contributor Author

github-actions Bot commented May 6, 2026

🔧 Repair Attempt 1/4

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 6, 2026

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Warm off-white background (#FAF8F1) — correct light theme surface. Title "waterfall-basic · highcharts · anyplot.ai" is visible at top-center in dark ink. Y-axis title "Amount ($)" is rotated on the left; x-axis category labels (Revenue, Product Costs, Operating Expenses, Marketing, R&D, Other Income, Taxes, Net Income) appear at the bottom in INK_SOFT dark grey; y-axis tick labels ($0–$540,000) are visible. Eight bars displayed left-to-right: Revenue (blue, $500k starting total), Product Costs / Operating Expenses / Marketing / R&D / Taxes (all vermillion-orange, negative), Other Income (brand green, positive), Net Income (blue, $158k ending total). Dotted horizontal connector lines link consecutive bars. Data labels (e.g. "+$500,000", "-$150,000", "$158,000") appear inside each bar in dark INK. All text is readable against the light background — no light-on-light issues. Legibility verdict: PASS.

Dark render (plot-dark.png): Near-black background (#1A1A17) — correct dark theme surface. Title text renders in light #F0EFE8; axis labels and tick labels appear in light INK_SOFT (#B8B7B0) against the dark background — no dark-on-dark text failures. Bar colors are identical to the light render: blue totals, vermillion-orange negatives, brand green for Other Income — confirming Okabe-Ito positions 1–3 are theme-invariant. Data labels appear in light INK (#F0EFE8) on the bars and are legible. Theme token switching works correctly throughout. Legibility verdict: PASS.

Both renders pass theme-readability checks.

Score: 83/100

Category Score Max
Visual Quality 26 30
Design Excellence 11 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 9 10
Library Mastery 7 10
Total 83 100

Visual Quality (26/30)

  • VQ-01: Text Legibility (6/8) — All font sizes explicitly set (28px title, 22px axis, 18px ticks) per style guide; readable in both themes but on-bar data labels could be larger at this canvas size
  • VQ-02: No Overlap (6/6) — No overlapping text elements in either render
  • VQ-03: Element Visibility (5/6) — Bars and connector lines clearly visible; data labels slightly small at 18px for a 4800×2700 canvas
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito positions 1–3 used; CVD-safe; adequate contrast throughout
  • VQ-05: Layout & Canvas (3/4) — Chart fills ~60% of canvas; upper-right area somewhat empty but not severe; 280px bottom margin prevents label clipping
  • VQ-06: Axis Labels & Title (2/2) — Y-axis "Amount ($)" with units; title format exact
  • VQ-07: Palette Compliance (2/2) — Brand green #009E73 for positive bars, vermillion #D55E00 for negatives, blue #0072B2 for totals; backgrounds #FAF8F1/#1A1A17 correct; data colors identical across themes; chrome fully adaptive

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (4/8) — Well-configured Highcharts default: clean palette, no chartjunk, but no standout design choices beyond the Okabe-Ito colors
  • DE-02: Visual Refinement (3/6) — Legend disabled, generous bottom margin, no visible chart border box, subtle dotted connector lines — above default but not exceptional
  • DE-03: Data Storytelling (4/6) — Color-coded bars (green gain, orange costs, blue totals) immediately communicate the financial story; waterfall cascade is clear; color alone creates meaningful visual hierarchy

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Highcharts native waterfall chart type used correctly
  • SC-02: Required Features (4/4) — All spec requirements met: color-coded positive/negative bars, dotted connector lines between bars, distinct start/end total bars (blue), data labels on every bar
  • SC-03: Data Mapping (3/3) — Categories on x-axis, dollar amounts on y-axis, correct cumulative flow
  • SC-04: Title & Legend (3/3) — Title "waterfall-basic · highcharts · anyplot.ai" exact format; legend disabled (single-series, appropriate)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows all waterfall features: positive change (Other Income), multiple negative changes, start total (Revenue), end total (Net Income)
  • DQ-02: Realistic Context (5/5) — Quarterly P&L breakdown from Revenue to Net Income — real-world business finance scenario, neutral and recognisable
  • DQ-03: Appropriate Scale (4/4) — Revenue $500k, costs proportional (30%/16%/9%/7%), net income $158k (31.6% margin) — internally consistent and plausible

Code Quality (9/10)

  • CQ-01: KISS Structure (3/3) — Linear flow: imports → tokens → data → chart options → JS download → HTML → screenshot → cleanup; no functions or classes
  • CQ-02: Reproducibility (2/2) — Data is fully deterministic (hardcoded values, no randomness)
  • CQ-03: Clean Imports (2/2) — All imported modules are used
  • CQ-04: Code Elegance (1/2) — Placeholder-replacement hack to inject JS formatter functions into a JSON string is fragile; CDN fallback logic adds unnecessary complexity
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html for both themes; current Selenium API

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Uses Highcharts native waterfall type, per-point isSum flag, per-point color overrides, and JS formatter functions — idiomatic but not expert-level
  • LM-02: Distinctive Features (3/5) — isSum flag for automatic cumulative sum at the final bar, per-point color overrides in the data array, and custom Highcharts.numberFormat formatters are Highcharts-specific capabilities

Score Caps Applied

  • None

Strengths

  • Uses Highcharts native waterfall chart type with isSum flag for accurate automatic cumulative sum tracking
  • Okabe-Ito palette applied correctly: brand green (#009E73) for positive changes, vermillion (#D55E00) for negatives, blue (#0072B2) for totals
  • Full theme-adaptive chrome: background, text (INK/INK_SOFT), and grid all switch correctly between light (#FAF8F1) and dark (#1A1A17)
  • All spec requirements met: color-coded bars, dotted connector lines, distinct start/end total bars, data labels on every bar
  • Realistic and internally consistent financial data (quarterly P&L from revenue to net income)

Weaknesses

  • Design Excellence is mid-tier: chart is a well-configured Highcharts default with no standout aesthetic touches — tighten inter-bar spacing, consider a subtle horizontal reference line at $0
  • Data label formatter labels the Revenue starting bar as "+$500,000" (change format) instead of "$500,000" (total format) — the isSum path in the formatter only applies to the final Net Income bar
  • JS formatter insertion via string placeholder replacement is a code smell — fragile approach; consider using a raw JavaScript string template or the highcharts_core Python API
  • Canvas utilisation is approximately 60% — significant empty space in the upper-right; reducing chart height or widening bars would help
  • Data labels inside bars are 18px which renders small at 4800×2700; 22–24px would improve on-bar readability

Issues Found

  1. DE-01 LOW: Chart is functional and correctly styled but lacks any distinctive design personality beyond correct palette usage
    • Fix: Increase bar padding to make bars slightly wider, add a horizontal zero-reference line, consider slightly larger data labels
  2. CQ-04 MINOR: __FORMATTER_PLACEHOLDER__ / __DATALABEL_FORMATTER_PLACEHOLDER__ injection into JSON string is fragile
    • Fix: Build the HTML template as a Python f-string with the JavaScript inlined directly rather than replacing placeholders in a JSON dump

AI Feedback for Next Attempt

Score 83/100 — APPROVED at attempt 2 threshold (≥80). No repair needed. The implementation correctly uses Highcharts' native waterfall series, applies the full Okabe-Ito palette, and passes theme-adaptive chrome in both renders. If regenerating: increase data label font size to 22–24px, fix the Revenue bar data label prefix (should be "$" not "+$" for starting totals), replace the placeholder-injection pattern with direct JS string embedding, and tighten bar padding for better canvas utilisation.

Verdict: APPROVED

@github-actions github-actions Bot added quality:83 Quality score 83/100 ai-approved Quality OK, ready for merge and removed quality:26 Quality score 26/100 labels May 6, 2026
@MarkusNeusinger MarkusNeusinger merged commit 5365b0c into main May 6, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/waterfall-basic/highcharts branch May 6, 2026 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-approved Quality OK, ready for merge ai-attempt-1 First repair attempt ai-review-failed AI review action failed or timed out quality:83 Quality score 83/100 quality-poor Score < 50, needs fundamental fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant